package tmt.usercenter.web.configure.security;

import org.apache.ignite.Ignite;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.approval.ApprovalStore;
import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import tmt.usercenter.web.configure.security.bean.IgniteTokenStore;

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

	@Autowired
	private AuthenticationManager authenticationManager;

	@Autowired
	@Qualifier("clientDetailsServiceImpl")
	private ClientDetailsService clientDetailsService;

	@Autowired
	@Qualifier("userDetailsServiceImpl")
	private UserDetailsService userDetailsService;

	@Autowired(required = false)
	private Ignite igniteInstance;

	@Autowired
	private ApprovalStore approvalService;

	@Autowired
	private UserApprovalHandler userApprovalHandler;

	@Bean
	@Primary
	public DefaultTokenServices tokenServices() {
		DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
		defaultTokenServices.setTokenStore(tokenStore());
		defaultTokenServices.setSupportRefreshToken(true);
		return defaultTokenServices;
	}

	@Bean
	@Primary
	public TokenStore tokenStore() {
		return igniteInstance != null ? new IgniteTokenStore(igniteInstance) : new InMemoryTokenStore();
	}

	/*@Bean
	public TokenStore tokenStore() {
		return new JdbcTokenStore(dataSource());
	}

	@Bean
	public DataSource dataSource() {
		DriverManagerDataSource dataSource =  new DriverManagerDataSource();
		dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
		dataSource.setUrl(env.getProperty("jdbc.url"));
		dataSource.setUsername(env.getProperty("jdbc.user"));
		dataSource.setPassword(env.getProperty("jdbc.pass"));
		return dataSource;
	}*/

	/**
	 * 用来配置令牌端点(Token Endpoint)的安全约束
	 *
	 * @param security
	 * @throws Exception
	 */
	@Override
	public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
		security
				/**
				 * 设置了allowFormAuthenticationForClients才会有ClientCredentialsTokenEndpointFilter，
				 *这点非常重要，ClientCredentialsTokenEndpointFilter是用来验证clientid和client_secret的，
				 *使用clientid和client_secret换取下一步的东西；
				 */
				.allowFormAuthenticationForClients() //允许表单认证
				.tokenKeyAccess("isAnonymous() || permitAll()")
				.checkTokenAccess("isAuthenticated() || permitAll()");
		super.configure(security);
	}

	/**
	 * 用来配置客户端详情服务（ClientDetailsService），客户端详情信息在这里进行初始化，
	 * 你能够把客户端详情信息写死在这里或者是通过数据库来存储调取详情信息。
	 * @param clients
	 * @throws Exception
	 */
	@Override
	public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
		clients.withClientDetails(clientDetailsService);
	}

	/**
	 * 用来配置授权（authorization）以及令牌（token）的访问端点和令牌服务(token services)。
	 * @param endpoints
	 * @throws Exception
	 */
	@Override
	public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
//        if (igniteInstance != null)
//            endpoints.tokenStore(igniteTokenStore());

		endpoints.tokenStore(tokenStore());
		endpoints
				.userDetailsService(userDetailsService)
				.authenticationManager(authenticationManager);

		//通过以下映射使用自定义的页面替换Spring Security默认的页面
		//endpoints.pathMapping("/oauth/confirm_access", "/extenal/oauth/confirm_access");

		endpoints.approvalStore(approvalService);
//		endpoints.userApprovalHandler(userApprovalHandler());
		endpoints.userApprovalHandler(userApprovalHandler);
	}
}
